<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>The New Yorker Style Converter</title>
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <link href="https://fonts.googleapis.com/css2?family=EB+Garamond:ital,wght@0,400;0,500;0,600;1,400;1,500&family=Playfair+Display:wght@400;500&display=swap" rel="stylesheet">
  <style>
* {
  box-sizing: border-box;
}

body {
margin: 0;
padding: 40px 20px;
min-height: 100vh;
background: #faf8f5;
font-family: ‘EB Garamond’, Georgia, serif;
color: #1a1a1a;
}

.container {
max-width: 720px;
margin: 0 auto;
}

header {
text-align: center;
margin-bottom: 48px;
padding-bottom: 32px;
border-bottom: 1px solid #1a1a1a;
}

.masthead {
font-family: ‘Playfair Display’, Georgia, serif;
font-size: 2.5rem;
font-weight: 400;
letter-spacing: 0.02em;
margin: 0 0 8px 0;
text-transform: uppercase;
}

.tagline {
font-style: italic;
font-size: 1.1rem;
color: #555;
margin: 0;
}

.editor-section {
margin-bottom: 32px;
}

label {
display: block;
font-size: 0.9rem;
text-transform: uppercase;
letter-spacing: 0.15em;
margin-bottom: 12px;
color: #666;
}

textarea {
width: 100%;
height: 180px;
padding: 20px;
font-family: ‘EB Garamond’, Georgia, serif;
font-size: 16px;
line-height: 1.7;
border: 1px solid #ccc;
background: #fff;
resize: vertical;
transition: border-color 0.2s ease;
}

textarea:focus {
outline: none;
border-color: #1a1a1a;
}

textarea::placeholder {
color: #999;
font-style: italic;
}

.output-container {
position: relative;
background: #fff;
border: 1px solid #1a1a1a;
padding: 24px;
min-height: 180px;
}

.output-text {
font-size: 1.15rem;
line-height: 1.8;
white-space: pre-wrap;
word-wrap: break-word;
}

.output-text:empty::before {
content: “Your refined text will appear here…”;
color: #999;
font-style: italic;
}

.copy-btn {
position: absolute;
top: 12px;
right: 12px;
padding: 8px 16px;
font-family: ‘EB Garamond’, Georgia, serif;
font-size: 0.85rem;
text-transform: uppercase;
letter-spacing: 0.1em;
background: #1a1a1a;
color: #fff;
border: none;
cursor: pointer;
transition: all 0.2s ease;
}

.copy-btn:hover {
background: #333;
}

.copy-btn:active {
transform: scale(0.98);
}

.copy-btn.copied {
background: #2d5016;
}

.ornament {
text-align: center;
margin: 40px 0;
font-size: 1.5rem;
color: #999;
}

footer {
text-align: center;
padding-top: 32px;
border-top: 1px solid #ddd;
font-size: 0.85rem;
color: #888;
font-style: italic;
}

.dinkus {
letter-spacing: 0.5em;
margin-bottom: 16px;
}
</style>

</head>
<body>
  <div class="container">
    <header>
      <h1 class="masthead">Style Converter</h1>
      <p class="tagline">In the manner of The New Yorker</p>
    </header>
<div class="editor-section">
  <label for="input">Your text</label>
  <textarea id="input" placeholder="Paste your text here to receive it back with proper diaereses, refined typography, and a certain je ne sais quoi…"></textarea>
</div>

<div class="ornament">❧</div>

<div class="editor-section">
  <label>Refined result</label>
  <div class="output-container">
    <button class="copy-btn" id="copyBtn">Copy</button>
    <div class="output-text" id="output"></div>
  </div>
</div>

<footer>
  <div class="dinkus">• • •</div>
  <p>Coöperating with tradition since the digital age</p>
</footer>
  </div>

<script type="module">
const input = document.getElementById('input');
const output = document.getElementById('output');
const copyBtn = document.getElementById('copyBtn');

const diaresisWords = {
  'cooperate': 'coöperate',
  'cooperates': 'coöperates',
  'cooperated': 'coöperated',
  'cooperating': 'coöperating',
  'cooperation': 'coöperation',
  'cooperative': 'coöperative',
  'cooperatives': 'coöperatives',
  'coordinator': 'coördinator',
  'coordinators': 'coördinators',
  'coordinate': 'coördinate',
  'coordinates': 'coördinates',
  'coordinated': 'coördinated',
  'coordinating': 'coördinating',
  'coordination': 'coördination',
  'reelect': 'reëlect',
  'reelects': 'reëlects',
  'reelected': 'reëlected',
  'reelecting': 'reëlecting',
  'reelection': 'reëlection',
  'reenter': 'reënter',
  'reenters': 'reënters',
  'reentered': 'reëntered',
  'reentering': 'reëntering',
  'reentry': 'reëntry',
  'reenact': 'reënact',
  'reenacts': 'reënacts',
  'reenacted': 'reënacted',
  'reenacting': 'reënacting',
  'reenactment': 'reënactment',
  'reengage': 'reëngage',
  'reengages': 'reëngages',
  'reengaged': 'reëngaged',
  'reengaging': 'reëngaging',
  'preeminent': 'preëminent',
  'preeminence': 'preëminence',
  'preempt': 'preëmpt',
  'preempts': 'preëmpts',
  'preempted': 'preëmpted',
  'preempting': 'preëmpting',
  'preemptive': 'preëmptive',
  'naive': 'naïve',
  'naively': 'naïvely',
  'naivete': 'naïveté',
  'naiveté': 'naïveté',
  'noel': 'noël',
  'zoe': 'zoë',
  'chloe': 'chloë',
  'bronte': 'brontë',
  'reexamine': 'reëxamine',
  'reexamines': 'reëxamines',
  'reexamined': 'reëxamined',
  'reexamining': 'reëxamining',
  'reestablish': 'reëstablish',
  'reestablishes': 'reëstablishes',
  'reestablished': 'reëstablished',
  'reestablishing': 'reëstablishing'
};

function convertToNewYorkerStyle(text) {
  let result = text;

  // Apply diaeresis replacements (case-insensitive)
  for (const [plain, diaeresis] of Object.entries(diaresisWords)) {
    const regex = new RegExp(`\\b${plain}\\b`, 'gi');
    result = result.replace(regex, (match) => {
      // Preserve original case
      if (match === match.toUpperCase()) {
        return diaeresis.toUpperCase();
      } else if (match[0] === match[0].toUpperCase()) {
        return diaeresis.charAt(0).toUpperCase() + diaeresis.slice(1);
      }
      return diaeresis;
    });
  }

  // Curly quote characters via Unicode
  const lsq = '\u2018';
  const rsq = '\u2019';
  const ldq = '\u201C';
  const rdq = '\u201D';

  // Single quotes
  result = result.replace(/(\s|^)'(\S)/g, '$1' + lsq + '$2');
  result = result.replace(/(\S)'(\s|$|[.,!?;:])/g, '$1' + rsq + '$2');
  result = result.replace(/'/g, rsq);

  // Double quotes
  result = result.replace(/(\s|^)"(\S)/g, '$1' + ldq + '$2');
  result = result.replace(/"(\s|$|[.,!?;:])/g, rdq + '$1');
  result = result.replace(/^"(\S)/gm, ldq + '$1');
  result = result.replace(/"$/gm, rdq);

  // Em dashes
  result = result.replace(/--/g, '\u2014');

  // Ellipsis
  result = result.replace(/\.\.\./g, '\u2026');

  return result;
}

function updateOutput() {
  const converted = convertToNewYorkerStyle(input.value);
  output.textContent = converted;
}

input.addEventListener('input', updateOutput);

copyBtn.addEventListener('click', async () => {
  const text = output.textContent;
  if (!text) return;

  try {
    await navigator.clipboard.writeText(text);
    copyBtn.textContent = 'Copied!';
    copyBtn.classList.add('copied');
    setTimeout(() => {
      copyBtn.textContent = 'Copy';
      copyBtn.classList.remove('copied');
    }, 2000);
  } catch (err) {
    console.error('Failed to copy:', err);
  }
});
</script>

</body>
</html>
